/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "物理异步解算.h"

#include <atomic>

static C_节点基类*	g_解算节点[128] = {};
static std::mutex	g_物理模拟线程锁;

static std::thread	g_Threads;
//static int32        g延迟 = 0;
//static bool		g_结束模拟解算 = false;
//static bool		g_是否更新节点 = true;
//static S_Physics*	g_线程物理对象[128] = {};

//static std::atomic_flag g物理计算是否完成 = ATOMIC_FLAG_INIT;
static volatile int g异步计算释放完成 = 1;
static volatile int g_线程模拟物理参数数量 = 0;

static void f_物理模拟线程() {
	++S_Engine::g_在运行线程;

	int32 g延迟 = 0;
	for (;;) {
		//std::cout << "线程" << std::endl;
		//线程退出一定要在锁之前 否则程序退出造成锁死状态
		if (S_NodeCtx_模拟计算::g_结束模拟解算) {
			break;
		}

		if (g异步计算释放完成 || !g_线程模拟物理参数数量) {
			std::this_thread::sleep_for(std::chrono::milliseconds(g延迟));
			if (g延迟 < 1000) g延迟 += 10;
		}
		else {
			g_物理模拟线程锁.lock();
			S_NodeCtx_模拟计算::g_是否更新节点 = false;

			for (uint8 i = 0; i < g_线程模拟物理参数数量; ++i) {
				//std::cout << "线程 begin" << std::endl;
				g_解算节点[i]->f_异步解算();
				//std::cout << "线程 end" << std::endl;
			}


			S_NodeCtx_模拟计算::g_是否更新节点 = true;
			
			g_物理模拟线程锁.unlock();
			g_线程模拟物理参数数量 = 0;
			
			//g物理计算是否完成.clear();
			g异步计算释放完成 = 1;
		}
	}

	--S_Engine::g_在运行线程;
}








void f_NodeCtx_物理模拟初始化() {
	S_NodeCtx_模拟计算::g_结束模拟解算 = false;
	g_Threads = std::thread(f_物理模拟线程);
}

void f_NodeCtx_物理模拟销毁() {
	S_NodeCtx_模拟计算::g_结束模拟解算 = true;
	g_物理模拟线程锁.lock();
	g_Threads.join();
	g_物理模拟线程锁.unlock();
}

bool f_NodeCtx_更新() {
	//return g异步计算释放完成;
	return g_物理模拟线程锁.try_lock();
}

bool f_NodeCtx_停止更新() {
	g_物理模拟线程锁.unlock();
	return false;
}

void f_NodeCtx_开始模拟计算() {
	S_NodeCtx_模拟计算::g_是否更新节点 = false;
}

void f_NodeCtx_结束模拟计算() {
	S_NodeCtx_模拟计算::g_是否更新节点 = true;
}

bool f_NodeCtx_等待计算完成(uint32 等待时间) {
	for (uint32 i = 0; i < 等待时间; ++i) {
		if (g异步计算释放完成 || !g_线程模拟物理参数数量) {
			return true;
		}
		std::this_thread::sleep_for(std::chrono::milliseconds(500));
	}
	return false;
}

bool f_NodeCtx_物理模拟线程入栈(S_Physics* phy) {
	//pthread_mutex_lock(&g_mutex);
	//if (g_mutex.try_lock()) {
		//g_mutex.lock();
	//g_线程物理对象[g_线程模拟物理参数数量] = phy;
	//++g_线程模拟物理参数数量;
	//std::cout << "g_线程模拟物理参数数量 = " << int32(g_线程模拟物理参数数量) << std::endl;
	//g_mutex.unlock();

	return true;
}



bool f_NodeCtx_物理模拟线程入栈(C_节点基类* node) {
	for (uint8 i = 0; i < g_线程模拟物理参数数量; ++i) {
		if (g_解算节点[i] == node) return false;
	}

	g_解算节点[g_线程模拟物理参数数量] = node;
	++g_线程模拟物理参数数量;
	//std::cout << "g_线程模拟物理参数数量 = " << int32(g_线程模拟物理参数数量) << std::endl;
	g异步计算释放完成 = 0;
	//g延迟 = 0;

	f_scene_设置光追渲染器渲染(f_NodeCtx_get默认场景(), true);
    return true;
}




int32 f_NodeCtx_get模拟步数() {
	return 1;
}

void f_NodeCtx_stop模拟步数() {
	
}

void f_NodeCtx_start模拟步数() {
	
}





